using Domain;
using ErrorCode;
using Infrastructure;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using RabbitTraceability.Api.Applications.Command;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace RabbitTraceability.Api.Applications.CommandHandler
{
    /// <summary>
    /// 保存养殖信息的命令处理器（添加或修改）
    /// </summary>
    public class SaveBreedingInfoCommandHandler : IRequestHandler<SaveBreedingInfoCommand, string>
    {
        private readonly IRepository<BreedingInfo> _repository;
        private readonly DataDbContext _context;
        private readonly ILogger<SaveBreedingInfoCommandHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="repository">养殖信息仓储</param>
        /// <param name="context">数据库上下文</param>
        /// <param name="logger">日志记录器</param>
        public SaveBreedingInfoCommandHandler(
            IRepository<BreedingInfo> repository,
            DataDbContext context,
            ILogger<SaveBreedingInfoCommandHandler> logger)
        {
            _repository = repository;
            _context = context;
            _logger = logger;
        }

        /// <summary>
        /// 处理保存养殖信息的命令
        /// </summary>
        /// <param name="request">请求命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>养殖信息编号</returns>
        public async Task<string> Handle(SaveBreedingInfoCommand request, CancellationToken cancellationToken)
        {
            // 参数验证
            ValidateRequest(request);
            try
            {
                // 使用事务确保数据一致性
                using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
                try
                {
                    string breedingId;
                    // 通过养殖编号判断是添加还是修改
                    if (!string.IsNullOrWhiteSpace(request.BreedingId))
                    {
                        // 修改现有养殖信息
                        _logger.LogInformation("修改养殖信息，养殖编号：{BreedingId}", request.BreedingId);
                        
                        // 查询现有养殖信息
                        var existingBreedingInfo = await _repository.GetAll()
                            .FirstOrDefaultAsync(b => b.BreedingId == request.BreedingId, cancellationToken);
                        
                        if (existingBreedingInfo == null)
                        {
                            _logger.LogWarning("未找到养殖信息，养殖编号：{BreedingId}", request.BreedingId);
                            throw new ApiException(ResultCode.数据不存在, $"未找到养殖编号为 {request.BreedingId} 的养殖信息");
                        }
                        
                        // 更新字段
                        existingBreedingInfo.Breed = request.Breed;
                        existingBreedingInfo.Source = request.Source;
                        existingBreedingInfo.FeedingDays = request.FeedingDays;
                        existingBreedingInfo.Brand = request.Brand;
                        existingBreedingInfo.BreederInCharge = request.BreederInCharge;
                        existingBreedingInfo.ProductionBatch = request.ProductionBatch;
                        
                        _context.Update(existingBreedingInfo);
                        breedingId = existingBreedingInfo.BreedingId;
                    }
                    else
                    {
                        // 创建新的养殖信息
                        _logger.LogInformation("添加养殖信息，批次：{ProductionBatch}", request.ProductionBatch);
                        
                        var newBreedingInfo = new BreedingInfo
                        {
                            Breed = request.Breed,
                            Source = request.Source,
                            FeedingDays = request.FeedingDays,
                            Brand = request.Brand,
                            BreederInCharge = request.BreederInCharge,
                            ProductionBatch = request.ProductionBatch
                        };
                        
                        await _context.BreedingInfos.AddAsync(newBreedingInfo, cancellationToken);
                        breedingId = newBreedingInfo.BreedingId;
                    }

                    // 保存更改
                    await _context.SaveChangesAsync(cancellationToken);
                    
                    // 提交事务
                    await transaction.CommitAsync(cancellationToken);
                    
                    _logger.LogInformation("保存养殖信息成功，编号：{BreedingId}", breedingId);
                    return breedingId;
                }
                catch (Exception ex)
                {
                    // 回滚事务
                    await transaction.RollbackAsync(cancellationToken);
                    _logger.LogError(ex, "保存养殖信息事务执行失败");
                    throw new ApiException(ResultCode.服务器错误, "保存养殖信息失败，请稍后再试");
                }
            }
            catch (ApiException)
            {
                // 直接抛出已经包装好的业务异常
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存养殖信息失败");
                throw new ApiException(ResultCode.服务器错误, "保存养殖信息失败，请稍后再试");
            }
        }

        /// <summary>
        /// 验证请求参数
        /// </summary>
        /// <param name="request">请求命令</param>
        private void ValidateRequest(SaveBreedingInfoCommand request)
        {
            if (string.IsNullOrWhiteSpace(request.Breed))
            {
                _logger.LogWarning("品种不能为空");
                throw new ApiException(ResultCode.参数错误, "品种不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.Source))
            {
                _logger.LogWarning("来源不能为空");
                throw new ApiException(ResultCode.参数错误, "来源不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.FeedingDays))
            {
                _logger.LogWarning("饲养天数不能为空");
                throw new ApiException(ResultCode.参数错误, "饲养天数不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.Brand))
            {
                _logger.LogWarning("品牌不能为空");
                throw new ApiException(ResultCode.参数错误, "品牌不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.BreederInCharge))
            {
                _logger.LogWarning("饲养负责人不能为空");
                throw new ApiException(ResultCode.参数错误, "饲养负责人不能为空");
            }

            if (string.IsNullOrWhiteSpace(request.ProductionBatch))
            {
                _logger.LogWarning("生产批次不能为空");
                throw new ApiException(ResultCode.参数错误, "生产批次不能为空");
            }
        }
    }
} 